package com.qiantu.phone.app;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Application;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.Uri;
import android.os.Build;
import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;

import com.alibaba.sdk.android.push.CloudPushService;
import com.alibaba.sdk.android.push.CommonCallback;
import com.alibaba.sdk.android.push.huawei.HuaWeiRegister;
import com.alibaba.sdk.android.push.noonesdk.PushServiceFactory;
import com.alibaba.sdk.android.push.notification.BasicCustomPushNotification;
import com.alibaba.sdk.android.push.notification.CustomNotificationBuilder;
import com.alibaba.sdk.android.push.register.MiPushRegister;
import com.alibaba.sdk.android.push.register.OppoRegister;
import com.alibaba.sdk.android.push.register.VivoRegister;
import com.facebook.cache.disk.DiskCacheConfig;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.imagepipeline.core.ImagePipeline;
import com.facebook.imagepipeline.core.ImagePipelineConfig;
import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.imagepipeline.request.ImageRequestBuilder;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.hjq.bar.TitleBar;
import com.hjq.base.BaseDialog;
import com.hjq.gson.factory.GsonFactory;
import com.hjq.http.EasyConfig;
import com.hjq.http.EasyLog;
import com.hjq.http.config.IRequestInterceptor;
import com.hjq.http.exception.ResponseException;
import com.hjq.http.lifecycle.ApplicationLifecycle;
import com.hjq.http.listener.HttpCallback;
import com.hjq.http.model.HttpHeaders;
import com.hjq.http.model.HttpParams;
import com.hjq.http.request.HttpRequest;
import com.hjq.toast.ToastUtils;
import com.hjq.umeng.UmengClient;
import com.qiantu.api.db.HouseDataManager;
import com.qiantu.api.db.LLControllerDBManager;
import com.qiantu.api.db.LLDeviceDBManager;
import com.qiantu.api.db.LLFloorDBManager;
import com.qiantu.api.db.LLHouseDBManager;
import com.qiantu.api.db.LLRoomDBManager;
import com.qiantu.api.db.LLSceneDBManager;
import com.qiantu.api.entity.ApplyTransferBean;
import com.qiantu.api.entity.HouseBean;
import com.qiantu.api.entity.LoginBean;
import com.qiantu.api.entity.SettingBean;
import com.qiantu.api.http.HttpBaseData;
import com.qiantu.api.http.LLHttpManager;
import com.qiantu.api.http.RequestHandler;
import com.qiantu.api.http.exception.TokenException;
import com.qiantu.api.http.model.HttpData;
import com.qiantu.api.http.model.RequestServer;
import com.qiantu.api.utils.FileUtils;
import com.qiantu.api.utils.ThemeUtil;
import com.qiantu.phone.BuildConfig;
import com.qiantu.phone.R;
import com.qiantu.phone.aop.Log;
import com.qiantu.phone.bean.LocationData;
import com.qiantu.phone.event.RefreshControllerEvent;
import com.qiantu.phone.event.RefreshDeviceListEvent;
import com.qiantu.phone.event.RefreshFloorRoomEvent;
import com.qiantu.phone.event.RefreshHomeWeatherSettingEvent;
import com.qiantu.phone.event.RefreshHouseEvent;
import com.qiantu.phone.event.RefreshLinkageEvent;
import com.qiantu.phone.event.RefreshSceneEvent;
import com.qiantu.phone.event.RefreshSceneIntentEvent;
import com.qiantu.phone.glide.GlideApp;
import com.qiantu.phone.manager.ActivityManager;
import com.qiantu.phone.utils.QTCrashHandler;
import com.qiantu.phone.other.DebugLoggerTree;
import com.qiantu.phone.other.MaterialHeader;
import com.qiantu.phone.other.SmartBallPulseFooter;
import com.qiantu.phone.other.TitleBarStyle;
import com.qiantu.phone.other.ToastLogInterceptor;
import com.qiantu.phone.other.ToastStyle;
import com.qiantu.phone.signalr.SignalRManager;
import com.qiantu.phone.ui.activity.FamilyInfoActivity;
import com.qiantu.phone.ui.activity.HomeActivity;
import com.qiantu.phone.ui.activity.HomeManagerActivity;
import com.qiantu.phone.ui.activity.InfoSupplementActivity;
import com.qiantu.phone.ui.activity.LoginActivity;
import com.qiantu.phone.ui.activity.MessageCenterActivity;
import com.qiantu.phone.ui.activity.SplashActivity;
import com.qiantu.phone.ui.activity.TransferAnimationActivity;
import com.qiantu.phone.ui.dialog.ConfirmCancelHintDialog;
import com.qiantu.phone.ui.dialog.ConfirmHintDialog;
import com.qiantu.phone.ui.dialog.MessagePopupDialog;
import com.qiantu.phone.ui.fragment.HomeFragment;
import com.qiantu.phone.utils.Constants;
import com.qiantu.phone.utils.PhoneUUIDUtils;
import com.qiantu.phone.utils.SPUtils;
import com.lxj.xpopup.XPopup;
import com.scwang.smart.refresh.layout.SmartRefreshLayout;
import com.tencent.bugly.crashreport.CrashReport;

import org.greenrobot.eventbus.EventBus;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Protocol;
import okhttp3.Response;
import timber.log.Timber;

/**
 * author : Android 轮子哥
 * github : https://github.com/getActivity/AndroidProject
 * time   : 2018/10/18
 * desc   : 应用入口
 */
public final class AppApplication extends Application {

    public static final String USER_PRIVACY_AGREEMENT_READ_KEY = "hasAgreed";
    private static AppApplication mInstance;
    public boolean isLocalNet = true;//当前是否为局域网。
    public final int openDelayTime = 1000;
    public final String GUID_ID = "1.0.1";//指引版本号

    private String userPhone;
    private LoginBean loginInfo;
    private HouseBean currentHouse;
    private String currentHouseSerialNo;
    public String pushDeviceId;
    public SettingBean mSettingBean;
    public LocationData currentLocation;

    private HouseDataManager mDataManager;
    private SignalRManager mSignalRManager;
    private CloudPushService pushService;

    @Log("启动耗时")
    @Override
    public void onCreate() {
        super.onCreate();
         mInstance = this;
        initThirdNeedPrivacy();
        getThemeResId();
        initActivityManager();
        initPushDeviceId();
        initUserInfo();
        initCurrentHouse();
        initMigu();
//        sHA1(getBaseContext());
    }

    private void initMigu() {
    }

    private void initActivityManager() {
        // Activity 栈管理初始化
        ActivityManager.getInstance().init(this);
        ActivityManager.getInstance().registerApplicationLifecycleCallback(new ActivityManager.ApplicationLifecycleCallback() {
            @Override
            public void onApplicationCreate(Activity activity) {}

            @Override
            public void onApplicationDestroy(Activity activity) {

            }

            @Override
            public void onApplicationBackground(Activity activity) {

            }

            @Override
            public void onApplicationForeground(Activity activity) {
                //应用从后台进入到前台
                //没有登录，或者(没有创建房屋也没跳转创建房屋)并且没有邀请进入房屋
                if(loginInfo == null || (loginInfo.getRegistrationProgress() < 3 && !loginInfo.isOwnHouse())){
                    return;
                }
                initHouseData();
            }
        });
    }

    public void initThirdNeedPrivacy() {
        if(!SPUtils.getInstance().getBoolean(Constants.USER_PRIVACY_AGREEMENT_READ_KEY)){
            return;
        }
        initSdk(this);
        // Bugly 异常捕捉
        CrashReport.initCrashReport(this, AppConfig.getBuglyId(), false);
        createNotificationChannel();
        //初始化云推送通道
        PushServiceFactory.init(this);
        registerPush();
        preLoadSceneIconAndAnimation();
        //捕获异常
        QTCrashHandler.getInstance().init(this);

    }

    private void initPushDeviceId() {
        pushDeviceId = SPUtils.getInstance().getString("pushDeviceId");
    }

    /**
     * 建立推送通道
     */
    public void registerPush() {
        pushService = PushServiceFactory.getCloudPushService();
        BasicCustomPushNotification notification = new BasicCustomPushNotification();
        notification.setRemindType(BasicCustomPushNotification.REMIND_TYPE_SOUND);
        notification.setStatusBarDrawable(R.mipmap.img_aboutapp);
        notification.setBuildWhenAppInForeground(false);
        /**
         * startHour
         * 免打扰的起始时间（小时），24小时制，取值范围：0-23。
         *
         * starMinute
         * 免打扰起始时间（分钟），取值范围：0-59。
         *
         * endHour
         * 免打扰的结束时间（小时），24小时制，取值范围：0-23。
         *
         * endMinute
         * 免打扰结束时间（分钟），取值范围：0-59。
         */
//        pushService.setDoNotDisturb(int startHour, int startMinute, int endHour, int endMinute, CommonCallback callback);
//        closeDoNotDisturbMode();
        pushService.setLogLevel(CloudPushService.LOG_DEBUG);
        // 注册方法会自动判断是否支持华为系统推送，如不支持会跳过注册。
        HuaWeiRegister.register(this);
        // 注册方法会自动判断是否支持小米系统推送，如不支持会跳过注册。
        MiPushRegister.register(this, BuildConfig.XIAOMI_PUSH_APP_ID, BuildConfig.XIAOMI_PUSH_APP_KEY);
        // vivo通道注册
        VivoRegister.register(this);
        // appKey/appSecret在OPPO开发者平台获取
        OppoRegister.register(this, BuildConfig.OPPO_PUSH_APP_KEY, BuildConfig.OPPO_PUSH_APP_SECRET);
        pushService.register(this, new CommonCallback() {
            @Override
            public void onSuccess(String response) {
                pushDeviceId = pushService.getDeviceId();
                SPUtils.getInstance().put("pushDeviceId", pushDeviceId);
                android.util.Log.d("lzx", "register onSuccess:" + pushDeviceId);
            }

            @Override
            public void onFailed(String errorCode, String errorMessage) {
                android.util.Log.d("lzx", "register onFailed");
            }
        });
//        // appId/appkey在魅族开发者平台获取
//        MeizuRegister.register(this, "appId", "appkey");
    }

    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            // 通知渠道的id
            String id = "101";
            // 用户可以看到的通知渠道的名字.
            CharSequence name = "博昀通知";
            // 用户可以看到的通知渠道的描述
            String description = "重要消息通知";
            int importance = NotificationManager.IMPORTANCE_HIGH;
            NotificationChannel mChannel = new NotificationChannel(id, name, importance);
            // 配置通知渠道的属性
            mChannel.setDescription(description);
            // 设置通知出现时的闪灯（如果 android 设备支持的话）
            mChannel.enableLights(true);
            mChannel.setLightColor(Color.GREEN);
            // 设置通知出现时的震动（如果 android 设备支持的话）
            mChannel.enableVibration(true);
            mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
            //最后在notificationmanager中创建该通知渠道
            mNotificationManager.createNotificationChannel(mChannel);
        }
    }

    public boolean needGuid() {//是否显示开机引导页
        String guidId = SPUtils.getInstance().getString("guid_id");
        if (GUID_ID.equals(guidId)) {
            return false;
        } else {
            return true;
        }
    }

    public void initSignalR() {
        if (loginInfo != null && !TextUtils.isEmpty(loginInfo.getToken())) {
            if(currentHouse != null && !TextUtils.isEmpty(currentHouse.getHouseSerialNo())){//前房屋不为空的情况，检查长连接
                if(mSignalRManager != null){
                    //当前长连接不是当前房屋的需要重新创建连接
                    if(!currentHouse.getHouseSerialNo().equals(mSignalRManager.getHouseSerialNo())){
                        mSignalRManager.stopConnect(false);
                        mSignalRManager = new SignalRManager();
                    }
                }else{
                    mSignalRManager = new SignalRManager();
                }
            }else{//当前房屋空的情况，断开长连接
                if(mSignalRManager != null){
                    mSignalRManager.stopConnect(false);
                    mSignalRManager = null;
                }
            }
        }
    }

    public void startSmartHome(AppActivity activity) {
        if (AppApplication.getInstance().getLoginInfo() == null) {
            LoginActivity.start(activity, "", "");
            activity.finish();
        } else {
            switch (AppApplication.getInstance().getLoginInfo().getRegistrationProgress()) {
                case 0:
                    LoginActivity.start(activity, "", "");
                    activity.finish();
                    break;
                case 1:
                    InfoSupplementActivity.start(activity);
                    activity.finish();
                    break;
                case 2:
                    //已拥有房屋就跳转首页
                    if(AppApplication.getInstance().getLoginInfo().isOwnHouse()){
                        resetHomeActivity(activity);
                    }else{
                        FamilyInfoActivity.start(activity);
                        activity.finish();
                    }
                    break;
                case 3:
                    resetHomeActivity(activity);
                    break;
            }
        }
    }


    public void initHouseData() {
        //初始化房屋下所有数据后，进入首页
        changeHouseData(null, null);
    }

    //切换房屋时，根据当前房屋SerialNo是否为空，空才会覆盖CurrentHouseSerialNo
    public void changeHouseData(AppActivity activity, String hint) {
        changeHouseData(activity, getCurrentHouseSerialNo(), false, hint, null);
    }

    //切换房屋时，根据当前房屋SerialNo是否为空或者isDelete来判断覆盖CurrentHouseSerialNo
    public void changeHouseData(AppActivity activity, boolean isDelete, String hint) {
        changeHouseData(activity, getCurrentHouseSerialNo(), isDelete, hint, null);
    }

    /**
     *
     * @param activity 为空的时候，后台刷新不跳转首页
     * @param houseSerialNo
     * @param isDelete
     * @param hint
     * @param listener
     */
    public void changeHouseData(AppActivity activity, String houseSerialNo, boolean isDelete, String hint,
                                HouseDataManager.OnListener listener) {
        if (mDataManager == null || mDataManager.isCanceled) {
            mDataManager = new HouseDataManager(this);
        }
//        WeakReference<AppActivity> currentActivity = new WeakReference<>(activity);
        if (activity != null && !TextUtils.isEmpty(hint)) {
            activity.showDialog(hint);
        }
        mDataManager.initHouseData(houseSerialNo, isDelete, new HouseDataManager.OnListener() {
            @Override
            public void onStart() {
                if (listener!= null) listener.onStart();
            }

            @Override
            public void onSuccess(HouseBean defaultHouse) {
                if (listener!= null) listener.onSuccess(defaultHouse);
                setCurHouseInfo(defaultHouse);
                //activity不为空或者后台返回房屋为空的时候，需要跳转首页，跳转并重启首页
                if(defaultHouse == null){
                    /**
                     * 空房屋直接显示空房屋界面不发刷新事件了，因为有些界面刷新需要当前房屋信息
                     */
                    Activity topActivity = ActivityManager.getInstance().getTopActivity();
                    resetHomeActivity(topActivity);
                }else{
                    if (activity != null) {
                        /**
                         * 跳转首页会清空所有activity，重新跳转到HomeActivity,会走onNewIntent来刷新HomeActivity是否空房屋
                         */
                        resetHomeActivity(activity);
                    }else{
                        //主要用于前后台刷新数据后来更新界面
                        EventBus.getDefault().post(new RefreshHouseEvent());
                    }
                    /**
                     * 这些刷新事件主要是刷新HomeActivity里的fragment，因为这些fragment正常情况是不会重建的
                     */
                    EventBus.getDefault().post(new RefreshHomeWeatherSettingEvent());
                    EventBus.getDefault().post(new RefreshFloorRoomEvent());
                    EventBus.getDefault().post(new RefreshControllerEvent());
                    EventBus.getDefault().post(new RefreshDeviceListEvent());
                    EventBus.getDefault().post(new RefreshSceneEvent());
                    EventBus.getDefault().post(new RefreshSceneIntentEvent());
                    EventBus.getDefault().post(new RefreshLinkageEvent());
                }
            }

            @Override
            public void onFailed(List<String> messages) {
                if (activity != null) {
                    if (messages == null || messages.size() == 0) {
                        activity.toast("初始化数据失败");
                    } else {
                        for (String msg : messages) {
                            activity.toast(msg);
                        }
                    }
                    //token过期后会清除登录信息，就不跳转首页了
//                    if (loginInfo == null) {
//                        return;
//                    }
//                if(activity instanceof SplashActivity){
//                    activity.finish();
//                }
//                    resetHomeActivity(activity);
                }
                if (listener!= null) listener.onFailed(messages);
            }

            @Override
            public void onEnd() {
                if (activity != null) {
                    activity.hideDialog();
                }
                if (listener!= null) listener.onEnd();
            }
        });
    }

    public void resetHomeActivity(Activity activity){
        if(activity == null || activity.isFinishing() || activity.isDestroyed()){
            return;
        }
        Intent intent = new Intent(this, HomeActivity.class);
        intent.putExtra(HomeActivity.INTENT_KEY_IN_FRAGMENT_CLASS, HomeFragment.class);
        intent.putExtra(HomeActivity.INTENT_KEY_IN_IS_RESET, true);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
        if(!(activity instanceof HomeActivity)){
            activity.finish();
        }
    }

    public String getUserPhone() {
        return userPhone;
    }

    public LoginBean getLoginInfo() {
        return loginInfo;
    }

    public static AppApplication getInstance() {
        return mInstance;
    }

    private void initUserInfo() {
        userPhone = SPUtils.getInstance().getString("phone");
        String userJson = SPUtils.getInstance().getString("loginInfo");
        if (!TextUtils.isEmpty(userJson)) {
            Gson gson = new Gson();
            loginInfo = gson.fromJson(userJson, LoginBean.class);
        }
    }

    private void initCurrentHouse() {
        currentHouseSerialNo = SPUtils.getInstance().getString("currentHouseSerialNo");
        if (TextUtils.isEmpty(currentHouseSerialNo)) {
            return;
        }
        currentHouse = LLHouseDBManager.getInstance(this).get(currentHouseSerialNo);
        if(SPUtils.getInstance().getString("lan_mode_ip") != null){
            HttpBaseData.getInstance().setLanIP(SPUtils.getInstance().getString("lan_mode_ip"));
            HttpBaseData.getInstance().setLanMode(SPUtils.getInstance().getBoolean("lan_mode"));
        }
        if(SPUtils.getInstance().getString("local_api_url") != null){
            HttpBaseData.getInstance().setLocalService(SPUtils.getInstance().getBoolean("is_net_service"));
            HttpBaseData.getInstance().setLocalServiceUrl(SPUtils.getInstance().getString("local_api_url"));
            HttpBaseData.getInstance().setLocalServiceWs(SPUtils.getInstance().getString("local_ws_url"));
        }
    }

    public void setCurLoginInfo(String account, LoginBean loginBean) {
        removeCurrentHouse();
        setPhone(account);
        // 更新Token
        EasyConfig.getInstance()
                .addHeader("Authorization", "Bearer " + loginBean.getToken());
        updateLoginInfo(loginBean);
    }

    public void setPhone(String phone) {
        this.userPhone = phone;
        SPUtils.getInstance().put("phone", phone);
    }

    public void updateLoginInfo(LoginBean loginBean) {
        this.loginInfo = loginBean;
        updateLoginInfo();
    }

    private List<LoginBean> mAccounts;
    public List<LoginBean> getAccounts(){
        if (mAccounts == null){
            mAccounts = FileUtils.loadAccountsFromFile(this);
        }
        if (mAccounts == null){
            mAccounts = new ArrayList<>();
        }
        return mAccounts;
    }

    public void updateLoginInfo() {
        if (loginInfo == null) return;
        if (loginInfo.getUserInfo() == null) return;
        if (loginInfo.getUserInfo().getUserSerialNo() == null) return;
        Gson gson = new Gson();
        SPUtils.getInstance().put("loginInfo", gson.toJson(loginInfo));

        if (mAccounts == null){
            mAccounts = FileUtils.loadAccountsFromFile(this);
        }
        if (mAccounts == null){
            mAccounts = new ArrayList<>();
        }
        if (mAccounts.isEmpty()){
            mAccounts.add(loginInfo);
        } else if (mAccounts.get(0).getUserInfo().getUserSerialNo().equals(loginInfo.getUserInfo().getUserSerialNo())){
            mAccounts.set(0, loginInfo);
        }else {
            Iterator<LoginBean> iterator = mAccounts.iterator();
            while (iterator.hasNext()){
                LoginBean bean = iterator.next();
                if (TextUtils.isEmpty(bean.getUserInfo().getUserSerialNo()) || bean.getUserInfo().getUserSerialNo().equals(loginInfo.getUserInfo().getUserSerialNo())){
                    iterator.remove();
                }
            }
            mAccounts.add(0, loginInfo);
        }
        FileUtils.saveAccounts(this, mAccounts);
    }

    public void setCurHouseInfo(HouseBean houseBean) {
        if (houseBean == null) {
            removeCurrentHouse();
        }else{
            currentHouseSerialNo = houseBean.getHouseSerialNo();
            this.currentHouse = houseBean;
            SPUtils.getInstance().put("currentHouseSerialNo", currentHouseSerialNo);
        }
    }

    public HouseBean getCurHouseInfo() {
        return currentHouse;
    }

    public void saveCurHouseInfo(){
        LLHouseDBManager.getInstance(this).put(currentHouse);
    }

    public String getCurrentHouseSerialNo() {
        return currentHouseSerialNo;
    }

    public void removeCurrentHouse() {
        currentHouseSerialNo = null;
        currentHouse = null;
        SPUtils.getInstance().remove("currentHouseSerialNo");
    }

    public void logout() {
        loginInfo = null;
        currentHouse = null;
        currentHouseSerialNo = null;
        mSettingBean = null;
        SPUtils.getInstance().remove("currentHouseSerialNo");
        SPUtils.getInstance().remove("loginInfo");
        LLHouseDBManager.getInstance(this).clearFromDB();
        LLFloorDBManager.getInstance(this).clearFromDB();
        LLRoomDBManager.getInstance(this).clearFromDB();
        LLControllerDBManager.getInstance(this).clearFromDB();
        LLDeviceDBManager.getInstance(this).clearFromDB();
        LLSceneDBManager.getInstance(this).clearFromDB();
        if (mSignalRManager != null) {
            mSignalRManager.stopConnect(false);
            mSignalRManager = null;
        }
        if (pushService != null) {
            pushService.clearNotifications();
        }
        if (mDataManager!=null){
            mDataManager.cancel();
            mDataManager = null;
        }
    }

    public void reconnectSignalR(){
        mSignalRManager.stopConnect(true);
    }

    public void logoutToLogin() {
        logout();
        Intent intent = new Intent(this, LoginActivity.class);
//        Activity activity = ActivityManager.getInstance().getTopActivity();
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
//        activity.overridePendingTransition(R.anim.open_right_in, R.anim.open_left_out);
    }

    /**
     * 注销
     */
    public void logoffToLogin(){
        removeLoginInfo(loginInfo);
        logout();
        LoginActivity.startFromLogOff(this, true);
    }

    private void removeLoginInfo(LoginBean loginBean) {
        Iterator<LoginBean> iterator = getAccounts().iterator();
        while (iterator.hasNext()){
            LoginBean bean = iterator.next();
            if (TextUtils.isEmpty(bean.getUserInfo().getUserSerialNo()) || bean.getUserInfo().getUserSerialNo().equals(loginBean.getUserInfo().getUserSerialNo())){
                iterator.remove();
            }
        }
        FileUtils.saveAccounts(this, mAccounts);
    }

    public void changeAccount(AppActivity activity, LoginBean loginBean){
        HouseBean oldHouseBean = currentHouse;//保留原始数据，如果切换失败就回退到之前状态
        LoginBean oldLoginBean = loginInfo;//保留原始数据，如果切换失败就回退到之前状态
        setCurLoginInfo(loginBean.getUserInfo().getPhone(), loginBean);
        if (mDataManager!=null){
            mDataManager.cancel();
            mDataManager = null;
        }
        mDataManager = new HouseDataManager(this);
        String phoneSerialNo = PhoneUUIDUtils.getDeviceUUID(AppApplication.getInstance());
        mDataManager.setChangeAccountData(phoneSerialNo, pushDeviceId);
        changeHouseData(activity, null, true, getString(R.string.changing_account), new HouseDataManager.OnListener() {
            @Override
            public void onFailed(List<String> errorMessages) {
                setCurLoginInfo(oldLoginBean.getUserInfo().getPhone(), oldLoginBean);
                setCurHouseInfo(oldHouseBean);
            }

            @Override
            public void onEnd() {
                mDataManager.cancel();
                mDataManager = null;
            }
        });
    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        // 清理所有图片内存缓存
        GlideApp.get(this).onLowMemory();
    }

    @Override
    public void onTrimMemory(int level) {
        super.onTrimMemory(level);
        // 根据手机内存剩余情况清理图片内存缓存
        GlideApp.get(this).onTrimMemory(level);
    }

    /**
     * 初始化一些第三方框架
     */
    public void initSdk(Application application) {
        ImagePipelineConfig pipelineConfig = ImagePipelineConfig.newBuilder(this)
                .setMainDiskCacheConfig(DiskCacheConfig.newBuilder(this)
                        .setBaseDirectoryPath(application.getCacheDir())//设置缓存目录文件
                        .setBaseDirectoryName("fresco/")//设置缓存名称
                        .setMaxCacheSize(50*1024*1024)//设置缓存大小
                        .build()).build();
        //初始化
        Fresco.initialize(this, pipelineConfig);
        // 设置标题栏初始化器
        TitleBar.setDefaultStyle(new TitleBarStyle());

        // 设置全局的 Header 构建器
        SmartRefreshLayout.setDefaultRefreshHeaderCreator((cx, layout) ->
                new MaterialHeader(application).setColorSchemeColors(AppApplication.getInstance().getThemeColor(R.attr.themeColor)));
        // 设置全局的 Footer 构建器
        SmartRefreshLayout.setDefaultRefreshFooterCreator((cx, layout) -> new SmartBallPulseFooter(application));
        // 设置全局初始化器
        SmartRefreshLayout.setDefaultRefreshInitializer((cx, layout) -> {
            // 刷新头部是否跟随内容偏移
            layout.setEnableHeaderTranslationContent(true)
                    // 刷新尾部是否跟随内容偏移
                    .setEnableFooterTranslationContent(true)
                    // 加载更多是否跟随内容偏移
                    .setEnableFooterFollowWhenNoMoreData(true)
                    // 内容不满一页时是否可以上拉加载更多
                    .setEnableLoadMoreWhenContentNotFull(false)
                    // 仿苹果越界效果开关
                    .setEnableOverScrollDrag(false);
        });

        // 初始化吐司
        ToastUtils.init(application, new ToastStyle());
        // 设置调试模式
        ToastUtils.setDebugMode(AppConfig.isDebug());
        // 设置 Toast 拦截器
        ToastUtils.setInterceptor(new ToastLogInterceptor());

        // 本地异常捕捉
        //CrashHandler.register(application);



        // 网络请求框架初始化
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .protocols(Collections.singletonList(Protocol.HTTP_1_1))
                .build();
        EasyConfig.with(okHttpClient)
                // 是否打印日志
                .setLogEnabled(true)
                // 设置服务器配置
                .setServer(new RequestServer())
                // 设置请求处理策略
                .setHandler(new RequestHandler(application))
                // 设置请求重试次数
                .setRetryCount(1)
                .setInterceptor(new IRequestInterceptor() {
                    @Override
                    public void interceptArguments(HttpRequest<?> httpRequest, HttpParams params, HttpHeaders headers) {
                        // 添加全局请求头
                        if (loginInfo != null && !TextUtils.isEmpty(loginInfo.getToken())) {
                            headers.put("Authorization", "Bearer " + loginInfo.getToken());
                        }
                        String phoneInfo = "(Android " + Build.VERSION.RELEASE + ";" + Build.BRAND + " " + Build.MODEL + ")";

                        headers.put("User-Agent:", "Linlu/" + BuildConfig.VERSION_NAME + " " + phoneInfo);
                        // 添加全局请求参数
                        // params.put("6666666", "6666666");
                    }

                    @Override
                    public Response interceptResponse(HttpRequest<?> httpRequest, Response response) throws Exception {
                        //token过期,并且当前登录信息不为空就跳转登录页
                        if (loginInfo != null) {
                            if (response.code() == 401) {
                                handleError401();
                                throw new TokenException("");
                            } else if (response.code() == 403) {
                                try {
                                    String text = response.body().string();
                                    // 打印这个 Json 或者文本
                                    EasyLog.printJson(httpRequest, text);
                                    Gson gson = new Gson();
                                    HttpData httpData = gson.fromJson(text, HttpData.class);
                                    if (httpData.getCode() == 90007){
                                        //校验用户与建筑(房屋，楼层，房间)的权限关系失败
                                        Observable.just("").observeOn(AndroidSchedulers.mainThread()).subscribe(s -> showLoseHouseDialog());
                                        throw new ResponseException("", response);//messge设为空，防止有接口调用弹出toast
                                    }else if (httpData.getCode() == 90010){//未查询到用户的数据信息
                                        handleError90010();
                                    }
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                        // 返回响应异常
                        return response;
                    }
                }).into();
        // 设置 Json 解析容错监听
        GsonFactory.setJsonCallback((typeToken, fieldName, jsonToken) -> {
            // 上报到 Bugly 错误列表
            CrashReport.postCatchedException(new IllegalArgumentException(
                    "类型解析异常：" + typeToken + "#" + fieldName + "，后台返回的类型为：" + jsonToken));
        });

        // 初始化日志打印
        if (AppConfig.isLogEnable()) {
            Timber.plant(new DebugLoggerTree());
        }

        // 注册网络状态变化监听
        ConnectivityManager connectivityManager = ContextCompat.getSystemService(application, ConnectivityManager.class);
        if (connectivityManager != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            connectivityManager.registerDefaultNetworkCallback(new ConnectivityManager.NetworkCallback() {
                @Override
                public void onLost(@NonNull Network network) {
                    Activity topActivity = ActivityManager.getInstance().getTopActivity();
                    if (!(topActivity instanceof LifecycleOwner)) {
                        return;
                    }

                    LifecycleOwner lifecycleOwner = ((LifecycleOwner) topActivity);
                    if (lifecycleOwner.getLifecycle().getCurrentState() != Lifecycle.State.RESUMED) {
                        return;
                    }

                    ToastUtils.show(R.string.common_network_error);
                }
            });
        }
    }

    //登录token已过期
    public void handleError401() {
        logoutToLogin();
        ToastUtils.show(R.string.http_token_error);
    }

    //账号已注销
    public void handleError90010() {
        ToastUtils.show(R.string.http_token_error);
        removeLoginInfo(loginInfo);
        logoutToLogin();
    }

    private BaseDialog mLoseHouseDialog;
    private void showLoseHouseDialog() {
        if (currentHouse == null){
            ToastUtils.show(R.string.http_data_error);
            logoutToLogin();
            return;
        }
        if (mLoseHouseDialog!=null && mLoseHouseDialog.getActivity() == ActivityManager.getInstance().getTopActivity()){
            return;
        }
        mLoseHouseDialog = new ConfirmHintDialog.Builder(ActivityManager.getInstance().getTopActivity())
                //.setHint(getString(R.string.unbind_switch_success))
                .setContent(String.format(getString(R.string.lose_house_msg), currentHouse.getName()))
                .setRightBtnText(getResources().getString(R.string.i_got_it))
                //.setHintIcon(R.attr.icon_remind_correct)
                .setListener(new ConfirmHintDialog.OnListener() {
                    @Override
                    public void onLeftClick(BaseDialog dialog) {

                    }

                    @Override
                    public void onConfirm(BaseDialog dialog) {
                        if (LLHouseDBManager.getInstance(getApplicationContext()).getAll().size()>1){
                            ActivityManager.getInstance().finishAllActivities();
                            HomeManagerActivity.start(getApplicationContext(), 2);
                        }else {
                            LLHouseDBManager.getInstance(getApplicationContext()).remove(currentHouseSerialNo);
                            currentHouse = null;
                            HomeActivity.start(getApplicationContext());
                        }
                    }
                })
                .create();
        mLoseHouseDialog.setCanceledOnTouchOutside(false);
        mLoseHouseDialog.show();
    }

    public void showPushDialog(String messageType, JsonObject data, String title, String summary) {
        Activity topActivity = ActivityManager.getInstance().getTopActivity();
        if (topActivity != null) {
            //过户推送
            if("40".equals(messageType)){
                String houseSerialNo = null;
                String transferSerialNo = null;
                JsonElement jsonElementHouseSerialNo = data.get("houseSerialNo");
                if(jsonElementHouseSerialNo != null){
                    houseSerialNo = jsonElementHouseSerialNo.getAsString();
                }
                JsonElement jsonElementTransferSerialNo = data.get("transferSerialNo");
                if(jsonElementTransferSerialNo != null){
                    transferSerialNo = jsonElementTransferSerialNo.getAsString();
                }
                if(!TextUtils.isEmpty(houseSerialNo) && !TextUtils.isEmpty(transferSerialNo)){
                     showTransferDialog((AppActivity) topActivity, summary, transferSerialNo, houseSerialNo, null);
                }
            }else {
                MessagePopupDialog messagePopupDialog = new MessagePopupDialog(topActivity);
                messagePopupDialog.setDialogClickListener(new MessagePopupDialog.DialogClickListener() {
                    @Override
                    public void onClick() {
                        Activity activity = ActivityManager.getInstance().getTopActivity();
                        Intent intent = new Intent(activity, MessageCenterActivity.class);
                        activity.startActivity(intent);
                    }
                });
                new XPopup.Builder(topActivity)
                        .dismissOnBackPressed(false)
                        .dismissOnClickOutside(false)
                        .isViewMode(true)
                        .enableDrag(false)
                        .hasShadowBg(false)
                        .isFullScreen(false)
                        .asCustom(messagePopupDialog);
                messagePopupDialog.setMessageType(messageType);
                messagePopupDialog.setMessageTitle(title);
                messagePopupDialog.setMessageContent(summary);
                messagePopupDialog.show();
            }
        }
    }

    public void showTransferDialog(AppActivity topActivity, String tip, String transferSerialNo, String houseSerialNo, String congratulations){
        topActivity.showConfirmCancelHintDialog(getString(R.string.transfer_prompt),
                tip, getString(R.string.later), getString(R.string.receive_now), getString(R.string.rejection),
                new ConfirmCancelHintDialog.OnListener() {
                    @Override
                    public void onLeftClick(BaseDialog dialog) {

                    }

                    @Override
                    public void onRightClick(BaseDialog dialog) {
                        //贺词是空那就先获取
                        if(TextUtils.isEmpty(congratulations)){
                            LLHttpManager.getTransferDetail(new ApplicationLifecycle(), transferSerialNo, new HttpCallback<HttpData<ApplyTransferBean>>(null){

                                @Override
                                public void onStart(Call call) {
                                    if(topActivity != null){
                                        topActivity.showDialog();
                                    }
                                }

                                @Override
                                public void onSucceed(HttpData<ApplyTransferBean> result) {
                                    ApplyTransferBean applyTransfer = result.getData();
                                    if(applyTransfer != null){
                                        switch (applyTransfer.getState()){
                                            case 1:
                                                approvalTransfer((AppActivity) topActivity, applyTransfer.getTransferSerialNo(), true, applyTransfer.getHouseSerialNo(), applyTransfer.getCongratulations());
                                                break;
                                            case 2:
                                                ToastUtils.show(R.string.transfer_received);
                                                break;
                                            case 3:
                                                ToastUtils.show(R.string.transfer_rejected);
                                                break;
                                            case 4:
                                                ToastUtils.show(R.string.transfer_canceled);
                                                break;
                                        }
                                    }
                                }

                                @Override
                                public void onFail(Exception e) {

                                }

                                @Override
                                public void onEnd(Call call) {
                                    if(topActivity != null){
                                        topActivity.hideDialog();
                                    }
                                }
                            });
                        }else{
                            approvalTransfer((AppActivity) topActivity, transferSerialNo, true, houseSerialNo, congratulations);
                        }
                    }
                }, new ConfirmCancelHintDialog.OnRightTopListener() {
                    @Override
                    public void onRightTopClick(BaseDialog dialog) {
                        approvalTransfer((AppActivity) topActivity, transferSerialNo, false, houseSerialNo, congratulations);
                    }
                });
    }

    private void approvalTransfer(AppActivity appActivity, String transferSerialNo, boolean accept, String houseSerialNo, String congratulations){
        LLHttpManager.approvalTransfer(new ApplicationLifecycle(), transferSerialNo, accept, new HttpCallback<HttpData<Void>>(null){
            @Override
            public void onStart(Call call) {
                if(appActivity != null){
                    appActivity.showDialog();
                }
            }

            @Override
            public void onSucceed(HttpData<Void> result) {
                if(accept){
                    Intent intent = new Intent(AppApplication.this, TransferAnimationActivity.class);
                    intent.putExtra("houseSerialNo", houseSerialNo);
                    intent.putExtra("congratulations", congratulations);
                    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(intent);
                    Activity activity = ActivityManager.getInstance().getTopActivity();
                    if(activity != null){
                        activity.overridePendingTransition(R.anim.anim_fade_in,R.anim.anim_fade_out);
                    }
                }
            }

            @Override
            public void onFail(Exception e) {
                ToastUtils.show(e.getMessage());
            }

            @Override
            public void onEnd(Call call) {
                if(appActivity != null){
                    appActivity.hideDialog();
                }
            }
        });
    }

    private void preLoadSceneIconAndAnimation() {
        String[] iconUrl = AppApplication.getInstance().getSceneIconsByThemeId();
        for (String url : iconUrl) {
            String animationImage = BuildConfig.APP_SCENE_BASE + url;
            ImageRequest request = ImageRequestBuilder
                    .newBuilderWithSource(Uri.parse(animationImage))
                    .build();
            //两套加载图片库都预加载下
            ImagePipeline imagePipeline = Fresco.getImagePipeline();
            imagePipeline.fetchDecodedImage(request, null);
        }
    }

    public int getThemeColor(int resId){
        Activity activity = ActivityManager.getInstance().getTopActivity();
        int color = 0x00000000;
        if(activity != null){
            int[] attrs = new int[]{resId};
            TypedArray typedArray = activity.obtainStyledAttributes(attrs);
            color = typedArray.getColor(0, 0x00000000);
            typedArray.recycle();
        }
        return color;
    }

    public ColorStateList getThemeColorStateList(int resId){
        Activity activity = ActivityManager.getInstance().getTopActivity();
        ColorStateList color = null;
        if(activity != null){
            int[] attrs = new int[]{resId};
            TypedArray typedArray = activity.obtainStyledAttributes(attrs);
            color = typedArray.getColorStateList(0);
            typedArray.recycle();
        }
        return color;
    }

    public Drawable getThemeDrawable(int resId){
        Activity activity = ActivityManager.getInstance().getTopActivity();
        Drawable drawable = null;
        if(activity != null){
            int[] attrs = new int[]{resId};
            TypedArray typedArray = activity.obtainStyledAttributes(attrs);
            drawable = typedArray.getDrawable(0);
            typedArray.recycle();
        }
        return drawable;
    }

    public boolean getThemeBoolean(int resId){
        Activity activity = ActivityManager.getInstance().getTopActivity();
        Boolean flag = null;
        if(activity != null){
            int[] attrs = new int[]{resId};
            TypedArray typedArray = activity.obtainStyledAttributes(attrs);
            flag = typedArray.getBoolean(0, true);
            typedArray.recycle();
        }
        return flag == null ? true : flag;
    }


    public int getThemeResId(){
        ThemeUtil.init(SPUtils.getInstance().getInt("themeId", 0));
        switch (ThemeUtil.themeId) {
            case ThemeUtil.THEME_BLACK_GOLD:
                return R.style.AppThemeBlackGold;
            case ThemeUtil.THEME_ORANGE:
                return R.style.AppThemeOrange;
            default:
                return R.style.AppTheme;
        }
    }

    public void saveThemeIdAndReset(int themeId){
        ThemeUtil.themeId = themeId;
        SPUtils.getInstance().put("themeId", themeId);
        restart();
    }

    public String[] getSceneIconsByThemeId(){
        String[] iconUrl = getResources().getStringArray(R.array.scene_icon);
//        for (int i=0; i<iconUrl.length; i++) {
//            iconUrl[i] = ThemeUtil.getIconThemeSuffix() + iconUrl[i];
//        }
        return iconUrl;
    }

    public String[] getSceneIntentIconsByThemeId(){
        String[] iconUrl = getResources().getStringArray(R.array.scene_intent_icon);
        for (int i=0; i<iconUrl.length; i++) {
            iconUrl[i] = iconUrl[i];
        }
        return iconUrl;
    }

    public int getResourceId(String name, String defType){
        return getResources().getIdentifier(name, defType, getPackageName());
    }

    private void restart(){
        Intent intent = new Intent(this, SplashActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
        Activity activity = ActivityManager.getInstance().getTopActivity();
        if(activity != null){
            activity.overridePendingTransition(R.anim.anim_fade_in,R.anim.anim_fade_out);
        }
    }

    public static String sHA1(Context context){
        try {
            @SuppressLint("PackageManagerGetSignatures")
            PackageInfo info = context.getPackageManager().getPackageInfo(
                    context.getPackageName(), PackageManager.GET_SIGNATURES);
            byte[] cert = info.signatures[0].toByteArray();
            MessageDigest md = MessageDigest.getInstance("SHA1");
            byte[] publicKey = md.digest(cert);
            StringBuilder hexString = new StringBuilder();
            for (byte b : publicKey) {
                String appendString = Integer.toHexString(0xFF & b)
                        .toUpperCase(Locale.US);
                if (appendString.length() == 1)
                    hexString.append("0");
                hexString.append(appendString);
                hexString.append(":");
            }
            String result = hexString.toString();
            return result.substring(0, result.length()-1);
        } catch (PackageManager.NameNotFoundException | NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static boolean isHuawei() {
        String manufacturer = Build.MANUFACTURER;
        //这个字符串可以自己定义,例如判断华为就填写huawei,魅族就填写meizu
        if ("HUAWEI".equalsIgnoreCase(manufacturer) || "huawei".equalsIgnoreCase(manufacturer)) {
            return true;
        }
        return false;
    }
}